package com.sl.debug;


import cn.hutool.core.io.BufferUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.socket.SocketUtil;
import cn.hutool.socket.nio.NioServer;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.noear.socketd.SocketD;
import org.noear.socketd.broker.BrokerFragmentHandler;
import org.noear.socketd.broker.BrokerListener;
import org.noear.socketd.transport.core.Entity;
import org.noear.socketd.transport.core.Listener;
import org.noear.socketd.transport.core.Message;
import org.noear.socketd.transport.core.Session;
import org.noear.socketd.transport.core.entity.EntityDefault;
import org.noear.socketd.transport.core.listener.SimpleListener;
import org.noear.socketd.transport.server.Server;
import org.noear.socketd.utils.RunUtils;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar
 *
 * @author hy
 */
@Slf4j
public class SquareLakeDebugApplication {


    @SneakyThrows
    public static void main(String[] args) {
        if (ObjectUtil.isNull(args)) {
            args = new String[0];
        }
        String port = System.getProperty("port");
//        System.out.println("参数："+JSONUtil.toJsonStr(args));
//        String port = ArrayUtil.get(args, 0);

        if (StrUtil.isBlank(port) || !NumberUtil.isNumber(port)) {
            port = "15005";
        }
        String finalPort = port;
        Log.log.info("启动端口:" + port);
        Listener listener = new SimpleListener() {
            @Override
            public void onMessage(Session session, Message message) throws IOException {

                Log.log.info("event:" + message.event());
                Log.log.info("entity:" + message.entity().dataAsString());

                String event = message.event();
                Entity entity = message.entity();

                JSONObject entries = null;

                if (ObjectUtil.isNotNull(entity)) {
                    String s = entity.dataAsString();
                    if (StrUtil.isNotBlank(s)) {
                        entries = JSONUtil.parseObj(s);
                    }
                }
                if (StrUtil.equals(event, "close")) {
                    Log.log.info("exit");
                    System.exit(0);
                } else if (StrUtil.equals(event, "connect")) {

                    JSONObject data = entries.getJSONObject("data");
                    String port = data.getStr("port");
                    //开始处理消息
                    try {
                        AttachingDebugger.attachToVM("127.0.0.1", port);
                    } catch (Exception e) {
                        EntityDefault entityDefault = Entity.of(BufferUtil.createUtf8(buildErrorResponse(e.getMessage())));
                        session.send("response", entityDefault);
                    }
                    buildSuccessResponse("连接成功");
                } else if (StrUtil.equals(event, "addBreakPoint")) {
                    //添加断点
                    AttachingDebugger.addBreakPoint("", 0);
                } else if (StrUtil.equals(event, "removeBreakPoint")) {
                    //添加断点
                    AttachingDebugger.removeBreakPoint("", 0);
                }
            }
        };

        //启动服务
        Server server = SocketD.createServer("sd:ws")
                .config(c -> c.port(Integer.parseInt(finalPort)))
                .listen(listener)
                .start();

        //添加安全停止
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            Log.log.info("退出...");
            RunUtils.runAndTry(server::stop);
        }));

        Log.log.info("启动成功...");

        //应该是启动一个websocket的，然后前端直接连接这个websocket

//        NioServer server = new NioServer(Integer.parseInt(port));
//
//        server.setChannelHandler((sc) -> {
//            ByteBuffer readBuffer = ByteBuffer.allocate(1024);
//            try {
//                // 从channel读数据到缓冲区
//                int readBytes = sc.read(readBuffer);
//                if (readBytes > 0) {
//                    // Flips this buffer.  The limit is set to the current position and then
//                    // the position is set to zero，就是表示要从起始位置开始读取数据
//                    readBuffer.flip();
//                    // returns the number of elements between the current position and the  limit.
//                    // 要读取的字节长度
//                    byte[] bytes = new byte[readBuffer.remaining()];
//                    // 将缓冲区的数据读到bytes数组
//                    readBuffer.get(bytes);
//                    String body = StrUtil.utf8Str(bytes);
////                    Console.log("[{}]: {}", sc.getRemoteAddress(), body);
//                    doWrite(sc, body);
//                } else if (readBytes < 0) {
//                    IoUtil.close(sc);
//                }
//            } catch (IOException e) {
//                throw new IORuntimeException(e);
//            }
//        });
//        server.listen();
    }


    public static String buildSuccessResponse(String message) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", "2000");
        map.put("isSuccess", true);
        map.put("data", message);
        map.put("message", null);
        return JSONUtil.toJsonStr(map);
    }

    public static String buildErrorResponse(String message) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", "5000");
        map.put("isSuccess", false);
        map.put("data", null);
        map.put("message", message);
        return JSONUtil.toJsonStr(map);
    }
}